<?php

/**
 * 合同应收款信息仓库
 * @author wangwx 2015-5-12
 */

namespace common\repositories\myhtsq;

use common\repositories\common\MyscrmContractSyncDeleteDataRepository;
use Exception;
use common\support\StringHelper;
use common\error\ErrorCode;
use common\repositories\BaseRepository;
use common\entities\myhtsq\ContractReceivableEntity;
use common\entities\myhtsq\InvoiceEntity;
use common\repositories\myhtsq\ErpUserRepository;
use yii\db\Query;
use common\entities\ContractEntity;

class ContractReceivableRepository extends BaseRepository
{

    /**
     * 构造方法
     * @param unknown $config (optional)
     */
    public function __construct($config = [])
    {
        parent::__construct($config);
    }

    public static function getReceivableEntity($receivableId)
    {
        return ContractReceivableEntity::find()
            ->where(['receivable_id' => $receivableId])
            ->one();
    }

    /**
     * 根据合同ID获取对应的应收款项明细
     * @param string $contractId 合同id
     * @param boolean $withBadDebt 是否包含坏账
     * @return array
     */
    public static function getReceivableInfoByContractId($contractId, $withBadDebt = true)
    {
        $query = ContractReceivableEntity::find()
            ->select("myscrm_contract_receivable.*,receivableItem.receivable_item_name,categoryItem.money_category_item_name,
                    myscrm_buss_account_types.type_name as revenue_type_name,`myscrm_buss_account_types`.`finance_type_name` AS `finance_type_name`,
                    myscrm_invoice_receivable.cur_billing_amount")
            ->leftJoin('myscrm_receivable_item receivableItem',
                'myscrm_contract_receivable.receivable_item_id = receivableItem.receivable_item_id')
            ->leftJoin('myscrm_money_category_item categoryItem',
                'myscrm_contract_receivable.money_category_item_id = categoryItem.money_category_item_id')
            ->leftJoin('myscrm_buss_account_types',
                'myscrm_contract_receivable.revenue_type = myscrm_buss_account_types.type_id')
            ->leftJoin('myscrm_invoice_receivable',
                'myscrm_contract_receivable.receivable_id = myscrm_invoice_receivable.receivable_id')
            ->where(['myscrm_contract_receivable.contract_id' => $contractId]);

        if (!$withBadDebt) {
            $query->andWhere('is_bad_debt != 1');
        }

        //exit($query->createCommand()->getRawSql());

        $query = $query->asArray()
            ->all();

        if (isset($query) && count($query) > 0) {
            foreach ($query as $k => $v) {
                $query[$k]["payee_name"] = ErpUserRepository::getUserNameByBuguid($v["payee_id"]);
                $query[$k]["unite_sales_name"] = ErpUserRepository::getUserNameByBuguid($v["unite_sales_id"]);
                $query[$k]["department_name"]=ErpBusinessUnitRepository::getBunameByBuguid($v["department_id"]);

                $invoices = self::getInvoiceInfoByReceivableId($v['receivable_id']);
                $invoiceNos = '';
                if (isset($invoices) && count($invoices) > 0) {
                    foreach ($invoices as $k1 => $v1) {
                        $invoiceNos += $v1['invoice_no'] + ';';
                    }

                    $invoiceNos = substr($invoiceNos, 0, strlen($invoiceNos) - 1);
                }
                $query[$k]['billing_invoice_no'] = $invoiceNos;
            }
        }

        return $query;
    }

    /**
     * 获取指定合同下的所有应收款金额
     * @param string $contractId 合同id
     * @return float
     */
    public static function getReceivableTotalAmountByContractId($contractId)
    {
        $totalAmount = 0;
        $query = ContractReceivableEntity::find()
            ->select('receivable_amount')
            ->where(['contract_id' => $contractId])
            ->andWhere('is_bad_debt = 0')
            ->asArray()
            ->all();

        if (isset($query) && count($query) > 0) {
            foreach ($query as $k => $v) {
                if (isset($v['receivable_amount']) && !empty($v['receivable_amount'])) {
                    $totalAmount += floatval($v['receivable_amount']);
                }
            }
        }

        return $totalAmount;
    }

    /**
     * 获取应收款ID获取已开票的发票信息
     * @param string $receivableId
     * @return array
     */
    public static function getInvoiceInfoByReceivableId($receivableId)
    {
        $query = InvoiceEntity::find()
            ->select('myscrm_invoice.*')
            ->leftJoin('myscrm_invoice_receivable', 'myscrm_invoice_receivable.invoice_id = myscrm_invoice.invoice_id')
            ->where(['receivable_id' => $receivableId])
            ->asArray()
            ->all();
        return $query;
    }

    /**
     * 根据应收款项Id获取对应的应收款
     * @param string $receivableId 应收款项Id
     * @return \common\entities\myhtsq\ContractReceivableEntity
     */
    public static function getContractReceivableById($receivableId)
    {
        return ContractReceivableEntity::findOne(['receivable_id' => $receivableId]);
    }

    /**
     * 新增合同应收款项
     * @param \common\models\myhtsq\ContractReceivableModel $contractReceivableModel
     * @param bool $isComeFromBusinessSystem 是否来自商机系统
     * @return boolean|string 失败返回false，成功返回应收款项Id
     */
    public static function addContractReceivable($contractReceivableModel, $isComeFromBusinessSystem = false)
    {
        try {
            $entity = new ContractReceivableEntity();
            $entity->setAttributes($contractReceivableModel->attributes);

            if ($isComeFromBusinessSystem === false) {//如果不是来自商机系统，则应收款ID由我们生成，如果是来自商机系统，应收款ID由对方提供
                if (!(isset($entity->receivable_id) && !empty($entity->receivable_id))) {
                    $entity->receivable_id = StringHelper::uuid();
                }
            }

            $result = $entity->save();
            if ($result === false) {
                return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_FORM_SAVE_FAIL, $entity->firstErrorMessage);
            } else {
                return $entity->primaryKey;
            }
        } catch (Exception $ex) {
            return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_FORM_SAVE_FAIL, $ex->getMessage());
        }
    }

    /**
     * 修改合同应收款项
     * @param \common\models\myhtsq\ContractReceivableModel $contractReceivableModel
     * @return boolean|string 失败返回false，成功返回应收款项Id
     */
    public static function updateContractReceivable($contractReceivableModel)
    {
        try {
            $entity = ContractReceivableEntity::find()->where(['receivable_id' => $contractReceivableModel->receivable_id])->one();
            if (!isset($entity)) {
                return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_NOT_EXISTS);
            }

            $entity->setAttributes($contractReceivableModel->attributes);
            $result = $entity->update();
            if ($result === false) {
                return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_FORM_SAVE_FAIL, json_encode($entity->getFirstErrors()));
            } else {
                return $entity->receivable_id;
            }
        } catch (Exception $ex) {
            return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_FORM_SAVE_FAIL, $ex->getMessage());
        }
    }

    /**
     * 修改合同应收款项
     * @param [];
     * @author zhoud01
     * @since 2017-7-28
     * @return boolean|string 失败返回false，成功返回应收款项Id
     */
    public static function updateContractReceivableByEstablish($arr)
    {
        try {
            $entity = ContractReceivableEntity::find()->where(['receivable_id' => $arr['receivable_id']])->one();
            if (!isset($entity)) {
                return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_NOT_EXISTS);
            }

            //TODO 修改合同数据

            $result = $entity->update();
            if ($result < 1) {
                return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_FORM_SAVE_FAIL, json_encode($entity->getFirstErrors()));
            } else {
                return $entity->receivable_id;
            }
        } catch (Exception $ex) {
            return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_FORM_SAVE_FAIL, $ex->getMessage());
        }
    }


    /**
     * 新增合同应收款项
     * @param [];
     * @author zhoud01
     * @since 2017-7-28
     * @return boolean|string 失败返回false，成功返回应收款项Id
     */
    public static function addContractReceivableByEstablish($arr,$contractId)
    {

       /*
        * 应收款名称  882-fd02-11e4-bed8-00155d02c832  receivable_item_id
        * 关联收入项  7f94a49d-fcf6-11e4-bed8-00155d02c832  revenue_type
        * 款项小类    4d17ed28-005a-11e5-bed8-00155d02c832  money_category_item_id
        * 收款人id   a3c8f32d-374b-4772-95e9-0f3a84f2f1a1  payee_id
        *
       */

        $receivable_item_id = '882-fd02-11e4-bed8-00155d02c832';
        $revenue_type = '7f94a49d-fcf6-11e4-bed8-00155d02c832';
        $money_category_item_id = '4d17ed28-005a-11e5-bed8-00155d02c832';
        $payee_id = 'a3c8f32d-374b-4772-95e9-0f3a84f2f1a1';
        $payment_condition = '款到开通授权';

        $contractReceivableAllByContractId = ContractReceivableEntity::find()->where(['contract_id' => $contractId,'add_type' => 2])->asArray()->all();
        $contractReceivableAllByContractId = array_column($contractReceivableAllByContractId,'receivable_id');
        $EstablishDateSet = array_column($arr,'EstablishTime');
        $results =[];
        $receivable_ids = [];
        foreach ($arr as $item){
            $merge = false;
            //TODO 一个合同ID下对于同一天只能产生一笔应收款,如果条件匹配则更新相关金额
            $receivable_date = @$item['EstablishTime'];
            $entities = ContractReceivableEntity::find()->where(['contract_id' => $contractId,'add_type' => 2,'receivable_date' => $receivable_date,'revenue_type' => $item['buss_type_id']])->all();
            if(!empty($entities)){
                foreach ($entities as $entity){
                    $invoice = InvoiceReceivableRepository::getInvoiceReceivablesByReceivableId($entity->receivable_id);
                    if(!empty($entity) && empty($invoice) && $merge){
                        $receivable_ids[] = $entity->receivable_id;
                        $entity->delete();
                    }else{
                        if(!empty($entity) && $entity->payee_id == $payee_id && $entity->is_bad_debt == 0) {
                            if ($item['summaryReceived'] > 0 && empty($invoice)) {
                                $entity->receivable_amount = $item['summaryReceived'];//理论上有这条记录就只需改钱
                                $entity->receivable_type = $item['ProductType']; //合同混合类型
                                $entity->modified_by = $_SESSION['__id'];
                                $entity->modified_on = date('Y-m-d H:i:s');
                                $entity->receivable_date = $item['EstablishTime'];
                                $entity->revenue_type = $item['buss_type_id']; //业务收入项
                                $merge = true;
                                $receivable_ids[] = $entity->receivable_id;
                                $results[] = $entity->save();
                            }
                        }
                    }

                }
            }else{
                $have = false;
                $entities = ContractReceivableEntity::find()->where(['contract_id' => $contractId,'add_type' => 2,'receivable_amount' => $item['summaryReceived'],'revenue_type' => $item['buss_type_id']])->all();
                if(!empty($entities)){
                    foreach ($entities  as $entity){
                        if($entity->receivable_date == $item['EstablishTime']){
                            $have = true;
                        }else{
                            $invoice = InvoiceReceivableRepository::getInvoiceReceivablesByReceivableId($entity->receivable_id);
                            if(!in_array($entity->receivable_date,$EstablishDateSet) ){
                                if(empty($invoice)){
                                    $receivable_ids[] = $entity->receivable_id;
                                    $entity->delete();
                                }
                            }else{
                                if($entity->revenue_type == $item['buss_type_id']){
                                    if(!empty($entity) && $entity->payee_id == $payee_id && $entity->is_bad_debt == 0 && $entity->receivable_date != $item['EstablishTime']) {
                                        $entity->receivable_type = $item['ProductType']; //合同混合类型
                                        $entity->modified_by = $_SESSION['__id'];
                                        $entity->modified_on = date('Y-m-d H:i:s');
                                        $receivable_ids[] = $entity->receivable_id;
                                        $entity->save();
                                    }
                                }
                            }
                        }
                    }
                }
                if(!$have){
                    if($item['summaryReceived'] > 0){
                        $entity = new ContractReceivableEntity();
                        //默认选项
                        $entity->receivable_item_id = $receivable_item_id;
                        $entity->revenue_type = $revenue_type;
                        $entity->money_category_item_id = $money_category_item_id;
                        $entity->payment_condition = $payment_condition;
                        $entity->payee_id = $payee_id;

                        $entity->receivable_id = StringHelper::uuid();
                        $entity->created_by = $_SESSION['__id'];
                        $entity->contract_id = $contractId;
                        $entity->receivable_amount = $item['summaryReceived'];//理论上有这条记录就只需改钱
                        $entity->receivable_date = $item['EstablishTime'];
                        $entity->performance_accounting_time = date('Y-m-d');
                        $entity->receivable_type = $item['ProductType']; //合同混合类型
                        $entity->revenue_type = $item['buss_type_id']; //业务收入项
                        $entity->add_type = 2;//标识为通过开通信息推送产生
                        $results[] = $entity->save();
                    }
                }
            }
        }

        $diffRevenue_ids = array_diff($contractReceivableAllByContractId,$receivable_ids);

        foreach ($diffRevenue_ids as $id){
            $entity = ContractReceivableEntity::find()->where(['receivable_id' => $id,'add_type' => 2])->one();
            $invoice = InvoiceReceivableRepository::getInvoiceReceivablesByReceivableId($entity->receivable_id);
            //绑了票的不能删
            if(empty($invoice)){
                $results[] = $entity->delete();
            }
        }

        $result = true;

        foreach ($results as $val){
            $result = $val;
            if($val === false){//有一次出现失败就表示失败了
                $result = false;
                break;
            }

        }

        return $result;

    }


    /**
     * 更新应收款信息单个字段
     * @param $receivableId
     * @param $data
     * @return bool|string
     */
    public static function updateContractReceivableField($receivableId, $data)
    {
        $entity = ContractReceivableEntity::find()->where(['receivable_id' => $receivableId])->one();
        if (!isset($entity)) {
            return self::setAndReturn(ErrorCode::ERR_CONTRACT_RECEIVABLE_NOT_EXISTS);
        }
        if (isset($data["receivable_date"]) && !empty($data["receivable_date"])) {
            $entity["receivable_date"] = $data["receivable_date"];
        }
        if (isset($data["payee_id"]) && !empty($data["payee_id"])) {
            $entity["payee_id"] = $data["payee_id"];
        }
        if (isset($data["department_id"]) && !empty( $data["department_id"])) {
            $entity["department_id"] = $data["department_id"];
        }
        return self::updateContractReceivable($entity);
    }

    /**
     * 获取应收到期日未收应收款
     * @param $expiredDate 到期日
     * @return array|\yii\db\ActiveRecord[]
     */
    public static function getReceivableExpiredRemind($expiredDate)
    {
        $query = ContractReceivableEntity::find()
            ->where(['receivable_date' => $expiredDate, 'is_bad_debt' => '0'])
            ->andWhere('receivable_amount<>received_amount')
            ->asArray()
            ->all();
        return $query;
    }

    /**
     * 获取发票对应的未回完款的应收
     * @param $invoiceId 发票id
     */
    public static function getNoReceivedByInvoice($invoiceId)
    {
        $query = ContractReceivableEntity::find()
            ->select('myscrm_contract_receivable.*')
            ->innerJoin('myscrm_invoice_receivable', 'myscrm_invoice_receivable.receivable_id=myscrm_contract_receivable.receivable_id and myscrm_contract_receivable.billing_amount<>myscrm_contract_receivable.received_amount')
            ->where(['myscrm_invoice_receivable.invoice_id' => $invoiceId])
            ->asArray()
            ->all();
        return $query;
    }

    /**
     * 已开票金额
     * @param type $contract_id
     * @return type
     */
    public static function getBillingAmountSum($contract_id)
    {
        return ContractReceivableEntity::find()->where(['contract_id' => $contract_id])->sum('billing_amount');
    }

    public static function getAllBillingAmountSumByContractIds($contractIds)
    {
        return ContractReceivableEntity::find()
            ->select('sum(billing_amount) as billing_amount, contract_id')
            ->where(['contract_id' => $contractIds])
            ->groupBy('contract_id')
            ->asArray()
            ->all();
    }

    /**
     * 已回款金额
     * @param type $contract_id
     * @return type
     */
    public static function getReceivedAmountSum($contract_id)
    {
        return ContractReceivableEntity::find()->where(['contract_id' => $contract_id])->sum('received_amount');
    }

    public static function getAllReceivedAmountSumByContractIds($contractIds)
    {
        return ContractReceivableEntity::find()
            ->select('sum(received_amount) as received_amount, contract_id')
            ->where(['contract_id' => $contractIds])
            ->groupBy('contract_id')
            ->asArray()
            ->all();
    }

    public static function getAllIsBadDebtByContractIds($contractIds)
    {
        return ContractReceivableEntity::find()
            ->select('is_bad_debt, contract_id')
            ->where(['contract_id' => $contractIds])
            ->asArray()
            ->all();
    }

    /**
     * 根据合同id删除
     * @param $contractId
     * @return int
     */
    public static function deleteByContractId($contractId)
    {
        /** @var MyscrmContractSyncDeleteDataRepository $contractSyncDeleteDataRepository */
        $contractSyncDeleteDataRepository = \Yii::createObject(MyscrmContractSyncDeleteDataRepository::className());

        $deleteData = ContractReceivableEntity::findAll(["contract_id" => $contractId]);

        $deleteResult = ContractReceivableEntity::deleteAll(["contract_id" => $contractId]);

        if($deleteResult > 0){
            foreach ($deleteData as $data){
                $contractSyncDeleteDataRepository->add('myscrm_contract_receivable', 'receivable_id', $data['receivable_id']);
            }
        }

        return $deleteResult;
    }

    /**
     * 判断是否存在
     * @param $contractId
     * @return bool
     */
    public static function hasReceivable($contractId){
        return ContractReceivableEntity::find()->where(["contract_id"=>$contractId])->exists();
    }

    public static function getReceivableByContractId($contractId)
    {
        return ContractReceivableEntity::find()
            ->where(["contract_id" => $contractId])
            ->all();
    }

    /**
     * 根据收款负责人获取合同ID
     * @param $payeeIds
     * @return array
     */
    public static function getContractIdsByPayeeIds($payeeIds){
        $res = [];
        if (empty($payeeIds)) {
            return $res;
        }
        $data=ContractReceivableEntity::find()->select("contract_id")->where(["payee_id"=>$payeeIds])->all();
        foreach ($data as $item){
            array_push($res,$item["contract_id"]);
        }
        return $res;
    }

    /**
     * 根据合同id,业务收入项获取合同应收
     * @param $contractId
     * @param $revenueType
     * @return array
     */
    public static function getReceivableByContractIdRevenueType($contractId,$revenueType)
    {
        return ContractReceivableEntity::find()
            ->where(["contract_id" => $contractId,"revenue_type" => $revenueType])
            ->all();
    }

    /**
     * 根据合同id,应收id获取回款
     * @param $contractId
     * @param $receivableId
     * @return array
     */
    public static function getPaymentByContractIdReceivableId($contractId,$receivableId)
    {
        $query = new Query();
        return $query->select("myscrm_contract_payment.*")
                    ->from('myscrm_contract_receivable')
                    ->leftJoin('myscrm_invoice_receivable','myscrm_invoice_receivable.receivable_id = myscrm_contract_receivable.receivable_id')
                    ->leftJoin('myscrm_invoice_payment','myscrm_invoice_payment.invoice_receivable_id = myscrm_invoice_receivable.invoice_receivable_id')
                    ->leftJoin('myscrm_contract_payment','myscrm_contract_payment.payment_id = myscrm_invoice_payment.payment_id')
                    ->where(["myscrm_contract_receivable.contract_id" => $contractId,"myscrm_contract_receivable.receivable_id" => $receivableId])
                    ->all((ContractEntity::getDb()));
    }


    /**
     * @param $contract_id
     * @param $time
     * @return bool
     */
    public static function updateReceivableDateWhen($contract_id,$time){
        $entity = ContractReceivableEntity::findOne(['contract_id'=>$contract_id]);
        if($entity){
            $entity->performance_accounting_time = $time;
            return $entity->save();
        }
    }

}
